#include "maindialog.h"
#include "ui_maindialog.h"


#include <QDir>
#include <QDateTime>
#include <QVideoEncoderSettings>
#include <QAudioEncoderSettings>
#include <QMessageBox>
#include <QFileDialog>
#include <QSettings>

#include <QxtMailMessage>
#include <QCameraImageProcessing>

//---------------------------------------------
MainDialog::MainDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MainDialog)
{
    this->ui->setupUi(this);
    this->camera.setViewfinder(this->ui->camViewWidget);
    this->mediaRecorder = new QMediaRecorder(&this->camera);
    this->imageCapture = new QCameraImageCapture(&this->camera);
    this->camera.setCaptureMode(QCamera::CaptureStillImage);
    this->camera.start();
    this->camera.availableDevices();
    this->imageProcessing = this->camera.imageProcessing();
    this->_initCameraList();
    this->_connectSlots();
    this->initPaths();
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::_initCameraList(){
    QList<QByteArray> devices = QCamera::availableDevices();
    QByteArray byteArray;
    foreach(byteArray, devices){
      QString description = QCamera::deviceDescription(byteArray);
      //qDebug() << byteArray << "," << description << "\n";
      this->ui->comboBoxCameraSource->addItem(description);
    }

}
//---------------------------------------------

//---------------------------------------------
void MainDialog::_connectSlots(){
    this->connect(this->ui->pushButtonSnapImage,
                  SIGNAL(clicked()),
                  SLOT(actionSnapImage()));
    this->connect(this->ui->pushButtonRecordVideo,
                  SIGNAL(clicked()),
                  SLOT(recordVideo()));
    this->connect(this->ui->pushButtonAutoSnap,
                  SIGNAL(clicked()),
                  SLOT(autoSnapImage()));
    this->connect(this->ui->pushButtonChooseImagesPath,
                  SIGNAL(clicked()),
                  SLOT(chooseSnapImagePath()));
    this->connect(this->ui->pushButtonChooseVideosPath,
                  SIGNAL(clicked()),
                  SLOT(chooseRecordVideoPath()));
    this->connect(this->ui->pushButtonChooseAutoSnapPath,
                  SIGNAL(clicked()),
                  SLOT(chooseAutoSnapImagePath()));
    this->connect(&this->timer,
                  SIGNAL(timeout()),
                  SLOT(_autoSnapImage()));
    this->connect(this->ui->pushButtonEmailTest,
                  SIGNAL(clicked()),
                  SLOT(actionTestSendingEmail()));
    this->connect(this->ui->pushButtonSaveSettings,
                  SIGNAL(clicked()),
                  SLOT(actionSaveSettings()));

    this->connect(&this->smtp,
                  SIGNAL(authenticationFailed(QByteArray)),
                  SLOT(authenticationFailed(QByteArray)));
    this->connect(&this->smtp,
                  SIGNAL(connectionFailed(QByteArray)),
                  SLOT(connectionFailed(QByteArray)));
    //this->connect(smtp, SIGNAL(mailSent(int)), SLOT(mailSent(int)));
    this->connect(&this->smtp,
                  SIGNAL(mailFailed(int,int,QByteArray)),
                  SLOT(mailFailed(int,int,QByteArray)));
    this->connect(this->ui->sliderContrast,
                  SIGNAL(valueChanged(int)),
                  SLOT(setContrast(int)));
    this->connect(this->ui->sliderDemoising,
                  SIGNAL(valueChanged(int)),
                  SLOT(setDenoisingLevel(int)));
    this->connect(this->ui->sliderWhiteBalance,
                  SIGNAL(valueChanged(int)),
                  SLOT(setManualWhiteBalance(int)));
    this->connect(this->ui->sliderSaturation,
                  SIGNAL(valueChanged(int)),
                  SLOT(setSaturation(int)));
    this->connect(this->ui->sliderSaturation,
                  SIGNAL(valueChanged(int)),
                  SLOT(setSaturation(int)));
    this->connect(this->ui->sliderSharpening,
                  SIGNAL(valueChanged(int)),
                  SLOT(setSharpeningLevel(int)));
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::initPaths(){
    if (this->settingsSaved()){
        QSettings settings("bettinger", "webcam recorder");
        QString imagePath = settings.value("imagePath").toString();
        this->ui->lineEditImagesPath->setText(imagePath);
        QString videoPath = settings.value("videoPath").toString();
        this->ui->lineEditVideosPath->setText(videoPath);
        QString autoSnapImagePath = settings.value("autoSnapImagePath").toString();
        this->ui->lineEditAutoSnapPath->setText(autoSnapImagePath);
        QString senderEmail = settings.value("senderEmail").toString();
        this->ui->lineEditEmailSender->setText(senderEmail);
        QString receiversEmails = settings.value("receiversEmails").toString();
        this->ui->lineEditEmailReceivers->setText(receiversEmails);
        QTime snappingTimeInterval = settings.value("snappingTimeInterval").toTime();
        this->ui->timeEditInterval->setTime(snappingTimeInterval);
    }else{
        this->resetDefaultSettings();
    }

}
//---------------------------------------------

//---------------------------------------------
bool MainDialog::settingsSaved(){
    QSettings settings("bettinger", "webcam recorder");
    bool saved = settings.childKeys().contains("imagePath",Qt::CaseInsensitive);
    return saved;
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::resetDefaultSettings(){
    QString pathStr = QDir::currentPath() + QDir::separator();
    QString imagesPath = pathStr + tr("images");
    QDir dir;
    dir.mkdir(imagesPath);
    this->ui->lineEditImagesPath->setText(imagesPath);
    QString videosPath = pathStr + tr("videos");
    dir.mkdir(videosPath);
    this->ui->lineEditVideosPath->setText(videosPath);
    QString autoSnapPath = pathStr + tr("autoSnap");
    dir.mkdir(autoSnapPath);
    this->ui->lineEditAutoSnapPath->setText(autoSnapPath);
    QTime timeInterval(0, 0, 10);
    this->ui->timeEditInterval->setTime(timeInterval);
    this->ui->lineEditEmailSender->setText("email@gmail.com");
    this->ui->lineEditEmailReceivers->setText("email1@gmail.com;email2@hotmal.fr");
}
//---------------------------------------------

//---------------------------------------------
MainDialog::~MainDialog(){
    delete ui;
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::actionSnapImage(){
    this->stopVideoRecording();
    this->stopAutoSnapping();
    QCamera::CaptureMode captureMode = this->camera.captureMode();
    if(captureMode != QCamera::CaptureStillImage){
      this->camera.setCaptureMode(QCamera::CaptureStillImage);
    }
    QString imagePath = this->ui->lineEditImagesPath->text();
    this->_snapImage(imagePath);
}
//---------------------------------------------

//---------------------------------------------
QString MainDialog::_snapImage(QString imagePath){
    this->camera.searchAndLock();
    imagePath += QDir::separator();
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString();
    imagePath +=  dateTimeString+ ".jpg";
    this->imageCapture->capture(imagePath);
    this->camera.unlock();
    return imagePath;
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::stopAutoSnapping(){
    this->timer.stop();
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::recordVideo(){
    this->stopAutoSnapping();
    QCamera::CaptureMode captureMode = this->camera.captureMode();
    if(captureMode != QCamera::CaptureVideo){
      this->camera.stop();
      this->camera.setCaptureMode(QCamera::CaptureVideo);
      this->camera.start();
    }
    if(this->ui->pushButtonRecordVideo->isChecked()){
        qDebug() << "recording started...\n";
        QString videoPath = this->ui->lineEditVideosPath->text();
        videoPath += QDir::separator();
        QDateTime dateTime = QDateTime::currentDateTime();
        QString dateTimeString = dateTime.toString();
        videoPath +=  dateTimeString + ".mp2";
        QUrl videoUrl(videoPath);

        //*
        QVideoEncoderSettings videoEncoderSettings;
        QAudioEncoderSettings audioEncoderSettings;
        videoEncoderSettings.setCodec("video/mpeg2");
        videoEncoderSettings.setResolution(640, 480);
        audioEncoderSettings.setCodec("audio/vorbis");
        audioEncoderSettings.setQuality(QtMultimediaKit::HighQuality);
        this->mediaRecorder->setEncodingSettings(audioEncoderSettings, videoEncoderSettings);
        //*/

        qDebug() << "videoPath: " << videoPath << "\n";
        this->mediaRecorder->setOutputLocation(QUrl(videoUrl));
        this->mediaRecorder->record();
        this->ui->pushButtonRecordVideo->setText(tr("Stop recording"));
    }else{
        this->stopVideoRecording();
        qDebug() << "recording finished\n";
    }
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::stopVideoRecording(){
    this->mediaRecorder->stop();
    this->ui->pushButtonRecordVideo->setText(tr("Video"));
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::autoSnapImage(){
    if(this->hasPassword()){
        this->stopVideoRecording();
        QCamera::CaptureMode captureMode = this->camera.captureMode();
        if(captureMode != QCamera::CaptureStillImage){
            this->camera.setCaptureMode(QCamera::CaptureStillImage);
        }
        if(this->ui->pushButtonAutoSnap->isChecked()){
            qDebug() << "Auto snaping started\n";
            QTime zero;
            int intervalInMsec = zero.msecsTo(this->ui->timeEditInterval->time());
            this->timer.start(intervalInMsec);
            this->ui->pushButtonAutoSnap->setText(tr("Stop auto snap"));
        }else{
            this->stopAutoSnapping();
            this->ui->pushButtonAutoSnap->setText(tr("Start auto snap"));
            qDebug() << "Auto snaping ended\n";
        }
    }else{
        QMessageBox::warning(this, tr("You have to type your gmail password"), tr("You have to type your gmail password"));
    }

}
//---------------------------------------------

//---------------------------------------------
void MainDialog::_autoSnapImage(){
    QString imagePath = this->ui->lineEditAutoSnapPath->text();
    imagePath = this->_snapImage(imagePath);
    QString senderEmail = this->ui->lineEditEmailSender->text();
    QString passwordSender = this->ui->lineEditPassword->text();
    QString receiversString = this->ui->lineEditEmailReceivers->text();
    //QStringList receivers = receiversString.split(";");
    QString emailServor = "smtp.gmail.com";
    QxtMailMessage email(senderEmail, receiversString);
    QDateTime currentDateTime = QDateTime::currentDateTime();
    QString currentDateTimeString = currentDateTime.toString();
    email.setSubject(tr("Auto webcam:") + currentDateTimeString);
    //email.setBody(tr("a test to check all informations are valid"));
    QxtMailAttachment attachment = QxtMailAttachment::fromFile(imagePath);
    email.addAttachment(imagePath, attachment);
    smtp.disconnectFromHost();
    smtp.setUsername(senderEmail.toAscii());
    smtp.setPassword(passwordSender.toAscii());
    smtp.connectToSecureHost(emailServor);
    smtp.send(email);

}
//---------------------------------------------

//---------------------------------------------
bool MainDialog::hasPassword(){
    QString passwordSender = this->ui->lineEditPassword->text();
    bool has = !passwordSender.isEmpty();
    return has;
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::chooseSnapImagePath(){
    QString currentSnapImagePath = this->ui->lineEditImagesPath->text();
    QString newDirPath = QFileDialog::getExistingDirectory(
            this,
            tr("Select a Directory"),
            currentSnapImagePath);
    if(!newDirPath.isEmpty()){
        this->ui->lineEditImagesPath->setText(newDirPath);
    }
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::chooseRecordVideoPath(){
    QString currentVideoPath = this->ui->lineEditVideosPath->text();
    QString newDirPath = QFileDialog::getExistingDirectory(
            this,
            tr("Select a Directory"),
            currentVideoPath);
    if(!newDirPath.isEmpty()){
        this->ui->lineEditVideosPath->setText(newDirPath);
    }
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::chooseAutoSnapImagePath(){
    QString currentAutoSnapImagePath = this->ui->lineEditAutoSnapPath->text();
    QString newDirPath = QFileDialog::getExistingDirectory(
            this,
            tr("Select a Directory"),
            currentAutoSnapImagePath);
    if(!newDirPath.isEmpty()){
        this->ui->lineEditAutoSnapPath->setText(newDirPath);
    }
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::actionSaveSettings(){
    QSettings settings("bettinger", "webcam recorder");
    QString imagePath = this->ui->lineEditImagesPath->text();
    settings.setValue("imagePath", imagePath);
    QString videoPath = this->ui->lineEditVideosPath->text();
    settings.setValue("videoPath", videoPath);
    QString autoSnapImagePath = this->ui->lineEditAutoSnapPath->text();
    settings.setValue("autoSnapImagePath", autoSnapImagePath);
    QTime snappingTimeInterval = this->ui->timeEditInterval->time();
    settings.setValue("snappingTimeInterval", snappingTimeInterval);
    QString senderEmail = this->ui->lineEditEmailSender->text();
    settings.setValue("senderEmail", senderEmail);
    //QString passwordSender = this->ui->lineEditPassword->text();
    QString receiversEmails = this->ui->lineEditEmailReceivers->text();
    settings.setValue("receiversEmails", receiversEmails);
}
//---------------------------------------------


//---------------------------------------------
void MainDialog::actionTestSendingEmail(){
    //*
    if(this->hasPassword()){
        QString imagePath = "test.jpg";
        QString senderEmail = this->ui->lineEditEmailSender->text();
        QString passwordSender = this->ui->lineEditPassword->text();
        QString receiversString = this->ui->lineEditEmailReceivers->text();
        //QStringList receivers = receiversString.split(";");
        QString emailServor = "smtp.gmail.com";
        QxtMailMessage email(senderEmail, receiversString);
        email.setSubject(tr("test webcam recorder"));
        email.setBody(tr("a test to check all informations are valid"));
        QxtMailAttachment attachment = QxtMailAttachment::fromFile(imagePath);
        email.addAttachment(imagePath, attachment);
        //QHash<QString,QString> headers;
        //headers.insert("from","the@keeper.com");
        //email.setExtraHeaders(headers);
        smtp.disconnectFromHost();
        smtp.setUsername(senderEmail.toAscii());
        smtp.setPassword(passwordSender.toAscii());
        smtp.connectToSecureHost(emailServor);
        smtp.send(email);
        //this->disconnect(smtp);
        //delete smtp;
    }else{
        QMessageBox::warning(this, tr("You have to type your gmail password"), tr("You have to type your gmail password"));
    }
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::authenticationFailed(const QByteArray & msg){
   QString lastError = msg;
   QMessageBox::critical(this, tr("Authentication failed"), lastError + tr("\nImpossible d'envoyer l'email. Vérifier votre connexion internet et les informations entrées"));
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::connectionFailed(const QByteArray & msg){
   QString lastError = msg;
   QMessageBox::critical(this, tr("Connection failed"), lastError + tr("\nImpossible d'envoyer l'email. Vérifier votre connexion internet et les informations entrées"));
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::mailSent(int mailID){
   QMessageBox::information(this, tr("Email envoyé"), tr("L'email a bien été envoyé"));
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::mailFailed(int mailID, int errorCode, const QByteArray & msg){
   QString lastError = msg;
   QMessageBox::critical(this, tr("Email failed"), lastError + tr("\nImpossible d'envoyer l'email. Vérifier votre connexion internet et les informations entrées"));
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::setContrast(int value){
    this->imageProcessing->setContrast(value);
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::setDenoisingLevel(int level){
    this->imageProcessing->setDenoisingLevel(level);
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::setManualWhiteBalance(int colorTemperature){
    this->imageProcessing->setManualWhiteBalance(colorTemperature);
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::setSaturation(int value){
    this->imageProcessing->setSaturation(value);
}
//---------------------------------------------

//---------------------------------------------
void MainDialog::setSharpeningLevel(int level){
    this->imageProcessing->setSharpeningLevel(level);
}
//---------------------------------------------

